package com.dj.mingkong.common.util;


import com.dj.mingkong.common.exception.BaseRuntimeException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.FastDateFormat;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;

public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
    public static final String YMD_DATA = "yyyy-MM-dd";
    public static final String YMD01_DATA = "yyyy/MM/dd";
    public static final String YMDHMS_DATA = "yyyy-MM-dd HH:mm:ss";
    public static final String YMDSTRING_DATA = "yyyyMMddHHmmss";
    public static final String YMDGB_DATA = "yyyy年MM月dd日";
    public static final String YMDTHMSGB_DATA = "yyyy年MM月dd日 HH时mm分ss秒";
    public static final String YMD24H_DATA = "yyyy-MM-dd HH:mm:ss";
    public static final String[] DAYNAMES = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
    public static final String YYYY = "yyyy";
    public static final String YYYY_MM = "yyyy-MM";
    public static final String YYYY_MM_DD = "yyyy-MM-dd";
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    public static final int ONE_DAY_MILLISECONDS = 86400000;
    public static final int ONE_HOUR_MILLISECONDS = 3600000;
    public static final int ONE_MINUTE_MILLISECONDS = 60000;
    public static final long ONE_YEAR_MILLISECONDS = 1471228928L;
    public static final String[] parsePatterns = new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    private DateUtils() {
    }

    public static int getYear() {
        return Calendar.getInstance().get(1);
    }

    public static int getMonth() {
        return Calendar.getInstance().get(2);
    }

    public static int getDayOfMonth() {
        return Calendar.getInstance().get(5);
    }

    public static int getDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(5);
    }

    public static String getDayOfWeek() {
        Calendar calendar = Calendar.getInstance();
        int dayOfWeek = calendar.get(7);
        return DAYNAMES[dayOfWeek - 1];
    }

    public static String getDateWeek(String date) {
        String dateWeek = null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(parseDate(date, "yyyy-MM-dd"));
        int dayOfWeek = calendar.get(7);
        dateWeek = dayOfWeek + "";
        return dateWeek;
    }

    public static String getYMD() {
        return getYMD("-");
    }

    public static String getYMD(String separator) {
        Calendar now = Calendar.getInstance();
        return now.get(1) + separator + (now.get(2) + 1) + separator + now.get(5);
    }

    public static String getYMD_CN() {
        Calendar now = Calendar.getInstance();
        return now.get(1) + "年" + (now.get(2) + 1) + "月" + now.get(5) + "日";
    }

    public static Date getToday() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        calendar.set(14, 0);
        return calendar.getTime();
    }

    public static int getDayDiff(Date start, Date end) {
        Date d1 = getDayBegin(start);
        Date d2 = getDayBegin(end);
        return (int) ((d2.getTime() - d1.getTime()) / 86400000L);
    }

    public static long getMiniteDiff(Date start, Date end) {
        return end.getTime() / 60000L - start.getTime() / 60000L;
    }

    public static String getTimeDiff(Date start, Date end) {
        int days = (int) ((end.getTime() - start.getTime()) / 86400000L);
        int hours = (int) ((end.getTime() - start.getTime()) / 3600000L % 24L);
        int minutes = (int) ((end.getTime() - start.getTime()) / 60000L % 60L);
        String timeDiff = "";
        if (days > 0) {
            timeDiff = days + "天";
        }

        timeDiff = timeDiff + hours + "小时" + minutes + "分";
        return timeDiff;
    }

    public static String getMonthFirstDay(Date date) {
        return formatDate(getMonthBegin(date), "yyyy-MM-dd");
    }

    public static String getMonthLastDay(Date date) {
        return formatDate(getMonthEnd(date), "yyyy-MM-dd");
    }

    public static Date getMonthBegin() {
        return getMonthBegin(new Date());
    }

    public static Date getMonthEnd() {
        return getMonthEnd(new Date());
    }

    public static Date getMonthBegin(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(5, 1);
        return getDayBegin(calendar);
    }

    public static Date getMonthEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, 1);
        calendar.set(5, 1);
        calendar.add(5, -1);
        return getDayEnd(calendar);
    }

    public static Date getDayBegin() {
        return getDayBegin(Calendar.getInstance());
    }

    public static Date getDayEnd() {
        return getDayEnd(Calendar.getInstance());
    }

    public static Date getDayBegin(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }

        return getDayBegin(calendar);
    }

    public static Date getDayBegin(Calendar calendar) {
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        calendar.set(14, 0);
        return calendar.getTime();
    }

    public static Date getDayEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }

        return getDayEnd(calendar);
    }

    public static Date getDayEnd(Calendar calendar) {
        calendar.set(11, 23);
        calendar.set(12, 59);
        calendar.set(13, 59);
        calendar.set(14, 999);
        return calendar.getTime();
    }

    public static Date addSeconds(Date date, int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(13, seconds);
        return calendar.getTime();
    }

    public static Date addMinutes(Date date, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(12, minutes);
        return calendar.getTime();
    }

    public static Date addHours(Date date, int hours) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(11, hours);
        return calendar.getTime();
    }

    public static Date addDays(Date date, int days) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(6, days);
        return calendar.getTime();
    }

    public static Date addMonths(Date date, int months) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(2, months);
        return calendar.getTime();
    }

    public static Date addYears(Date date, int years) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(1, years);
        return calendar.getTime();
    }

    public static int getAge(Date birthday) {
        if (birthday == null) {
            return 0;
        } else {
            long time = (System.currentTimeMillis() - birthday.getTime()) / 1000L;
            return time < 0L ? 0 : (int) (time / 31536000L);
        }
    }

    public static Calendar getCalendar(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(time);
        return calendar;
    }

    public static Date getDate(long time) {
        Calendar calendar = getCalendar(time);
        return calendar.getTime();
    }

    public static String YYYYMMDD(Date date) {
        if (date == null) {
            return "";
        } else {
            FastDateFormat dateFormat = FastDateFormat.getInstance("yyyy-MM-dd");
            return dateFormat.format(date);
        }
    }

    public static String YYYYMMDDHHMMSS(Date date) {
        if (date == null) {
            return "";
        } else {
            FastDateFormat dateFormat = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
            return dateFormat.format(date);
        }
    }

    public static String formatDate(Date date, String pattern) {
        if (pattern == null) {
            return "";
        } else if (date == null) {
            return "";
        } else {
            FastDateFormat dateFormat = FastDateFormat.getInstance(pattern);
            return dateFormat.format(date);
        }
    }

    public static String formatDate(Calendar date, String pattern) {
        if (pattern == null) {
            return "";
        } else if (date == null) {
            return "";
        } else {
            FastDateFormat dateFormat = FastDateFormat.getInstance(pattern);
            return dateFormat.format(date);
        }
    }

    public static LocalDateTime timestampToDatetime(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    public static long dateTimeToTimestamp(LocalDateTime ldt) {
        return ldt.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    public static Date parseDate(String date, String pattern) {
        if (pattern == null) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }

        if (StringUtils.isBlank(date)) {
            return null;
        } else {
            FastDateFormat dateFormat = FastDateFormat.getInstance(pattern);

            try {
                return dateFormat.parse(date);
            } catch (ParseException var4) {
                var4.printStackTrace();
                throw new BaseRuntimeException(var4.getMessage());
            }
        }
    }

    public static Date getStartOfDay(Date date) {
        return org.apache.commons.lang3.time.DateUtils.truncate(date, 5);
    }

    public static Date getEndOfDay(Date date) {
        return org.apache.commons.lang3.time.DateUtils.addMilliseconds(org.apache.commons.lang3.time.DateUtils.ceiling(date, 5), -1);
    }

    public static Date getNowDate() {
        return new Date();
    }

    public static String getDate() {
        return dateTimeNow("yyyy-MM-dd");
    }

    public static String getTime() {
        return dateTimeNow("yyyy-MM-dd HH:mm:ss");
    }

    public static String dateTimeNow() {
        return dateTimeNow("yyyyMMddHHmmss");
    }

    public static String dateTimeNow(String format) {
        return parseDateToStr(format, new Date());
    }

    public static String dateTime(Date date) {
        return parseDateToStr("yyyy-MM-dd", date);
    }

    public static String parseDateToStr(String format, Date date) {
        return (new SimpleDateFormat(format)).format(date);
    }

    public static Date dateTime(String format, String ts) {
        try {
            return (new SimpleDateFormat(format)).parse(ts);
        } catch (ParseException var3) {
            throw new RuntimeException(var3);
        }
    }

    public static String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    public static String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        } else {
            try {
                return parseDate(str.toString(), parsePatterns);
            } catch (ParseException var2) {
                return null;
            }
        }
    }

    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 86400000L;
        long nh = 3600000L;
        long nm = 60000L;
        long diff = endDate.getTime() - nowDate.getTime();
        long day = diff / nd;
        long hour = diff % nd / nh;
        long min = diff % nd % nh / nm;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    public static Date getDaysBefore(Date date, int amount) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.add(5, amount);
        return ca.getTime();
    }

    public static Date getSeveralWeeks(int severalWeeks) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(7, severalWeeks);
        return calendar.getTime();
    }

    public static Date[] getBeginAndEndOfTheWeek(int week, int firstDayOfWeek) {
        Date nowDate = Calendar.getInstance().getTime();
        int daysOfWeek = 7;
        if (week != 0) {
            nowDate = addDays(nowDate, week * daysOfWeek);
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowDate);
        calendar.setFirstDayOfWeek(firstDayOfWeek);
        int dayOfWeek = calendar.get(7);
        calendar.set(5, firstDayOfWeek - dayOfWeek);
        Date beginDate = calendar.getTime();
        calendar.set(5, daysOfWeek);
        Date endDate = calendar.getTime();
        return new Date[]{beginDate, endDate};
    }

    public static int getDayOfWeek(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(7);
    }

    public static int getWeekOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(2);
        calendar.setTime(new Date());
        return calendar.get(4);
    }

    public static Date getDayEndWithZeroMis(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(11, 23);
        calendar.set(12, 59);
        calendar.set(13, 59);
        calendar.set(14, 0);
        return calendar.getTime();
    }


    /**
     * 获取指定哪周的第一天
     *
     * @return
     */
    public static Date getWeekStart(Integer amount) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.WEEK_OF_MONTH, amount);
        cal.set(Calendar.DAY_OF_WEEK, 2);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取指定那周的最后一天
     *
     * @return
     */
    public static Date getWeekEnd(Integer amount) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.WEEK_OF_MONTH, amount);
        cal.set(Calendar.DAY_OF_WEEK, 1);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    /**
     * 指定哪月的第一天
     *
     * @return
     */
    public static Date getMonthStart(Integer num) {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY) - num, cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    /**
     * 获取某年某月的最后一天
     */
    public static Date getMonthEnd(Integer num) {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY) - num, cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    /**
     * 本季度开始时间
     *
     * @return
     */
    public static Date getQuarterStart() {
        Calendar c = Calendar.getInstance();
        int currentMonth = c.get(Calendar.MONTH) + 1;
        SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
        Date now = null;
        try {
            if (currentMonth >= 1 && currentMonth <= 3)
                c.set(Calendar.MONTH, 0);
            else if (currentMonth >= 4 && currentMonth <= 6)
                c.set(Calendar.MONTH, 3);
            else if (currentMonth >= 7 && currentMonth <= 9)
                c.set(Calendar.MONTH, 4);
            else if (currentMonth >= 10 && currentMonth <= 12)
                c.set(Calendar.MONTH, 9);
            c.set(Calendar.DATE, 1);
            now = longSdf.parse(shortSdf.format(c.getTime()) + " 00:00:00");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return now;
    }

    /**
     * 指定哪季度结束时间
     *
     * @return
     */
    public static Date getQuarterEnd(Integer amount) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getQuarterStart());
        cal.add(Calendar.MONTH, amount);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }
}
